package com.easylinkin.linkappapi.lobar.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.lobar.dto.LaborCompanyProjectDTO;
import com.easylinkin.linkappapi.lobar.dto.UserClockDTO;
import com.easylinkin.linkappapi.lobar.dto.UserGateDTO;
import com.easylinkin.linkappapi.lobar.dto.app.AppUserGateDTO;
import com.easylinkin.linkappapi.lobar.entity.UserGate;
import com.easylinkin.linkappapi.lobar.entity.UserProject;
import com.easylinkin.linkappapi.lobar.entity.UserStatistics;
import com.easylinkin.linkappapi.lobar.mapper.LaborCompanyProjectMapper;
import com.easylinkin.linkappapi.lobar.mapper.UserGateMapper;
import com.easylinkin.linkappapi.lobar.mapper.UserProjectMapper;
import com.easylinkin.linkappapi.lobar.mapper.UserStatisticsMapper;
import com.easylinkin.linkappapi.lobar.service.UserGateService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.lobar.util.PercentageUtils;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 闸机表 服务实现类
 * </p>
 *
 * @author kanyuanfeng
 * @since 2022-04-13
 */
@Service
public class UserGateServiceImpl extends ServiceImpl<UserGateMapper, UserGate> implements UserGateService {

  @Resource
  private LinkappUserContextProducer linkappUserContextProducer;

  @Autowired
  private LaborCompanyProjectMapper laborCompanyProjectMapper;

  @Autowired
  private UserProjectMapper userProjectMapper;

  @Autowired
  private UserStatisticsMapper userStatisticsMapper;

  /**
   * 增加
   * @param userGate
   */
  @Override
  public void insert(UserGate userGate) {
    /**
     * 验证重复
     */
//    this.checkExist(userGate);
    //设置基本属性
    this.setBase(userGate);
    this.save(userGate);
  }

  /**
   * 根据id编辑
   * @param userGate
   */
  @Override
  public void updateOne(UserGate userGate) {
    /**
     * 验证重复
     */
//    this.checkExist(userGate);
    //设置基本属性
    this.setBase(userGate);
    this.updateById(userGate);
  }


  /**
   * @Description: 根据条件，分页(不分页)查询月视图
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public IPage<UserGateDTO> queryMonthByPage(RequestModel<UserGateDTO> requestModel)
      throws InterruptedException, ExecutionException {
    Page page = requestModel.getPage();
    UserGateDTO userGateDTO = requestModel.getCustomQueryParams();
    //项目id 过滤
    userGateDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    IPage<UserGateDTO> userGateIPage = baseMapper.queryMonthByPage(page, userGateDTO);
    //计算总天数
    String[] split = userGateDTO.getMouthStr().split("-");
    int lengthOfMonth = DateUtil
        .lengthOfMonth(Integer.valueOf(split[1]), DateUtil.isLeapYear(Integer.valueOf(split[0])));
    //查询当月所有的扫码数据
    //userId 排除
    if (null != userGateIPage.getRecords() && userGateIPage.getRecords().size() > 0){
      Set<String> ids = userGateIPage.getRecords().stream().map(u -> u.getUserId())
          .collect(Collectors.toSet());
      userGateDTO.setIds(ids);
      List<UserGate> userGates = baseMapper.findAllByMonth(userGateDTO);
      userGates.forEach(u->{
        //体温保留两位小数
        if (null != u.getTemperature()){
          Double aDouble = Double.valueOf(new DecimalFormat("#.0").format(u.getTemperature()));
          u.setTemperature(aDouble);
        }
      });
      CompletionService<UserGateDTO> completionService = new ExecutorCompletionService(Executors
          .newFixedThreadPool(30));
      userGateIPage.getRecords().forEach(r ->{
        completionService.submit(() -> setData(lengthOfMonth, userGates, r));
      });
      for (int i = 0; i < userGateIPage.getRecords().size(); i++) {
        completionService.take().get();
      }
    }
    return userGateIPage;
  }

  private UserGateDTO setData(int lengthOfMonth, List<UserGate> userGates, UserGateDTO r) {
    SimpleDateFormat d = new SimpleDateFormat("d");
    int onNum = 0;
    List<UserGate> newList = userGates.stream()
        .filter(u -> u.getUserId().equals(r.getUserId()))
        .collect(Collectors.toList());
    List<UserGateDTO> sonList = new ArrayList<>();
    for (int i = 1; i <= lengthOfMonth; i++) {
      UserGateDTO userGate = new UserGateDTO();
      userGate.setId(i+"");
      int finalI = i;
      List<UserGate> list = newList.stream()
          .filter(u -> Integer.valueOf(d.format(u.getTime())).equals(finalI))
          .collect(Collectors.toList());
      if (list.size()>0){
        userGate.setOnFlagStr("√");
        onNum++;
      }
      userGate.setMouthList(BeanUtil.copyToList(list,UserGateDTO.class));
      sonList.add(userGate);
    }
    r.setMouthList(sonList);
    r.setOnNum(onNum);
    return r;
  }

  /**
   *app健康管理首页统计
   */
  @Override
  public AppUserGateDTO countSum(Date date) {
    AppUserGateDTO appUserGateDTO = new AppUserGateDTO();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //判断是否今天
    DateTime time = DateUtil.beginOfDay(date);
    DateTime dateTime = DateUtil.beginOfDay(new Date());
    if (time.equals(dateTime)){
      //当天总人数
      QueryWrapper<UserProject> queryWrapper1 = new QueryWrapper<>();
      queryWrapper1.eq("tenant_id_",tenantId)
          .eq("status_",1);
      Integer integer = userProjectMapper.selectCount(queryWrapper1);
      appUserGateDTO.setSum(integer);
    }else {
      //非当天总人数
      QueryWrapper<UserStatistics> queryWrapper2 = new QueryWrapper<>();
      queryWrapper2.eq("tenant_id_",tenantId)
          .ge("record_time_",time).le("record_time_",DateUtil.endOfDay(time));
      List<UserStatistics> userStatistics = userStatisticsMapper.selectList(queryWrapper2);
      int sum = userStatistics.stream().mapToInt(u -> u.getSum()).sum();
      appUserGateDTO.setSum(sum);
    }
    QueryWrapper<UserGate> queryWrapper3 = new QueryWrapper<>();
    queryWrapper3.eq("tenant_id_",tenantId)
        .ge("time_",time).le("time_",DateUtil.endOfDay(time));
    List<UserGate> userGates = baseMapper.selectList(queryWrapper3);
    //测温人数
    appUserGateDTO.setTemperature(userGates.size());
    //绿码人数
    long count = userGates.stream().filter(u -> Integer.valueOf(1).equals(u.getHealthCode()))
        .count();
    appUserGateDTO.setGreenCode((int)count);
    //覆盖率
    appUserGateDTO.setCoverage(PercentageUtils.computePercentOne(userGates.size(),appUserGateDTO.getSum()));
    //通过率
    appUserGateDTO.setPassRate(PercentageUtils.computePercentOne((int)count,appUserGateDTO.getSum()));
    return appUserGateDTO;
  }

  /**
   *app参建单位统计
   */
  @Override
  public List<AppUserGateDTO> getCompany(Date date) {
    List<AppUserGateDTO> appUserGateDTOS;
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //判断是否今天
    DateTime time = DateUtil.beginOfDay(date);
    DateTime dateTime = DateUtil.beginOfDay(new Date());
    if (time.equals(dateTime)){
      appUserGateDTOS = baseMapper.findCompanyToDay(tenantId,time,DateUtil.endOfDay(date));
    }else {
      appUserGateDTOS = baseMapper.findCompanyTime(tenantId,time,DateUtil.endOfDay(date));
    }
    appUserGateDTOS.forEach(a->{
      a.setCoverage(PercentageUtils.computePercentOne(a.getTemperature(),a.getSum()));
    });
    return appUserGateDTOS;
  }

  /**
   *app班组统计
   */
  @Override
  public List<AppUserGateDTO> getGroup(String companyProjectId, Date date) {
    List<AppUserGateDTO> appUserGateDTOS;
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //判断是否今天
    DateTime time = DateUtil.beginOfDay(date);
    DateTime dateTime = DateUtil.beginOfDay(new Date());
    UserGateDTO userGateDTO = new UserGateDTO();
    userGateDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    userGateDTO.setCompanyProjectId(companyProjectId);
    userGateDTO.setStartTime(DateUtil.beginOfDay(date));
    userGateDTO.setEndTime(DateUtil.endOfDay(date));
    if (time.equals(dateTime)){
      appUserGateDTOS = baseMapper.findGroupToDay(userGateDTO);
    }else {
      appUserGateDTOS = baseMapper.findGroupTime(userGateDTO);
    }
    appUserGateDTOS.forEach(a->{
      a.setCoverage(PercentageUtils.computePercentOne(a.getTemperature(),a.getSum()));
    });
    return appUserGateDTOS;
  }

  /**
   *app人员统计
   */
  @Override
  public List<UserGateDTO> getUser(String companyProjectId, String groupId, Date date) {
    UserGateDTO userGateDTO = new UserGateDTO();
    userGateDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    userGateDTO.setCompanyProjectId(companyProjectId);
    userGateDTO.setGroupId(groupId);
    userGateDTO.setStartTime(DateUtil.beginOfDay(date));
    userGateDTO.setEndTime(DateUtil.endOfDay(date));
    List<UserGateDTO> userGateDTOS = baseMapper.findUser(userGateDTO);
    return userGateDTOS;
  }

  @Override
  public IPage<UserGateDTO> queryListByPage(RequestModel<UserGateDTO> requestModel) {
    Page page = requestModel.getPage();
    UserGateDTO userGateDTO = requestModel.getCustomQueryParams();
    //项目id 过滤
    userGateDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    Page page1 = new Page();
    page1.setSize(100000);
    LaborCompanyProjectDTO laborCompanyProjectDTO = new LaborCompanyProjectDTO();
    laborCompanyProjectDTO.setTenantId(userGateDTO.getTenantId());
    IPage<LaborCompanyProjectDTO> laborCompanyProjectDTOIPage = laborCompanyProjectMapper
        .queryListByPage(page1, laborCompanyProjectDTO);
    IPage<UserGateDTO> userGateIPage = baseMapper.queryListByPage(page, userGateDTO);
    userGateIPage.getRecords().forEach(r ->{
      //设置参建单位
      List<LaborCompanyProjectDTO> dtos = laborCompanyProjectDTOIPage.getRecords().stream()
          .filter(re -> r.getCompanyProjectId().equals(re.getCompanyProjectId()))
          .collect(Collectors.toList());
      if (dtos.size() > 0){
        r.setCompanyName(dtos.get(0).getName());
      }
      //体温保留2位小数
      if (null != r.getTemperature()){
        Double aDouble = Double.valueOf(new DecimalFormat("#.0").format(r.getTemperature()));
        r.setTemperature(aDouble);
      }
    });
    return userGateIPage;
  }

  /**
   * 验证重复
   */
  private void checkExist(UserGate userGate) {
    QueryWrapper<UserGate> queryWrapper = new QueryWrapper<>();
    //todo 设置判断重复条件
    //编辑的时候存在id
    Optional.ofNullable(userGate.getId()).ifPresent(id -> queryWrapper.ne("id",userGate.getId()));
    Integer integer = baseMapper.selectCount(queryWrapper);
    if (integer>0){
      throw new BusinessException("该闸机已存在");
    }
  }

  /**
   * 设置基本属性
   * @param userGate
   */
  private void setBase(UserGate userGate) {
    userGate.setModifyTime(new Date());
    if (null != linkappUserContextProducer.getCurrent()){
      userGate.setModifyId(linkappUserContextProducer.getCurrent().getId());
    }
    //没有id就是新增,有就是编辑
    if (StringUtils.isBlank(userGate.getId()) ){
      if (null != linkappUserContextProducer.getCurrent()){
        userGate.setCreatorId(linkappUserContextProducer.getCurrent().getId());
      }
      userGate.setCreateTime(new Date());
      if (StringUtils.isBlank(userGate.getTenantId())){
        userGate.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
      }
    }
  }
}
